

#include "..\Inc\includes.h"

/**************************************************************************
 * 函数名		：DelayForWork()
 * 输入参数 ：无
 * 输出参数 ：无
 * 返回值  	：无
 * 修改时间 ：2017-09-15
 * 函数描述 ：死循环延时，每个延时接近1毫秒
 *************************************************************************/											
void DelayForWork(unsigned short int u16_delay)
{
	unsigned short int				u16_loop;																											//1100最接近延时1mS
	
	for (; u16_delay>0; u16_delay--)
	{
		for (u16_loop=1100; u16_loop>0;u16_loop--);
	}
}
/**************************************************************************
 * 函数名		：UartSendByte()
 * 输入参数 ：无
 * 输出参数 ：无
 * 返回值  	：无
 * 修改时间 ：2018-09-30
 * 函数描述 ：发送一个字节数据。
 *************************************************************************/
 void UartSendByte(unsigned char u8_data)
 {
		SBUF = u8_data;																																				//发送值放SBUF中，
		while (TI==0);																																				//等待发送完毕
		TI = 0;																																								//发送完必须将TI清零
 }

/**************************************************************************
 * 函数名		：UartSendDataFrame()
 * 输入参数 ：无
 * 输出参数 ：无
 * 返回值  	：无
 * 修改时间 ：2018-09-30
 * 函数描述 ：发送一帧数据,1mS时基调用，9600,波特率差不多刚好1毫秒发送一个字节
 *						
 *************************************************************************/
 void UartSendDataFrame(unsigned char *p_u8_data)
 {
		unsigned char						u8_xor_count = 0,																							//异或校验字节数计数
														u8_xor_temp = 0;																							//异或临时寄存器
		static unsigned char		u8_send_count = 0,																						//发送字节数计数
														u8_send_state = 0,																						//发送状态，不为0为发送状态
														u8_frame_send_stop_count = 0;																	//发送帧与帧之间的间隙时间计数
		static unsigned char		u8_uart_send_data_buffer[20]={0};															//发送的一帧数据备份										 
	
	if (u8_frame_send_stop_count==0)																												//开始发送
	{
		if (!u8_send_state)																																		//发送数据前的准备
		{			
			for (u8_xor_count=0;u8_xor_count<(SEND_LENGTH_OF_ARRAY-1);u8_xor_count++)						//将除校验存放寄存器外的其他字节做备份
			{
				u8_uart_send_data_buffer[u8_xor_count] = (*(p_u8_data+u8_xor_count));							//备份数据防止发送过程中数据被修改造成传送错误
			}
			
			for (u8_xor_count=0;u8_xor_count<(SEND_LENGTH_OF_ARRAY-1);u8_xor_count++)						//将除校验存放寄存器外的其他字节中的值做异或
			{
				u8_xor_temp ^= u8_uart_send_data_buffer[u8_xor_count];
			}
			u8_uart_send_data_buffer[u8_xor_count] = u8_xor_temp;																//将做好的校验值存放到发送数据的最后一个字节中
			
			u8_send_state = 0x01;																																//发送准备只允许在发送一帧数据前做一次，发送中不允许修改发送值
		}
		
		UartSendByte(u8_uart_send_data_buffer[u8_send_count]);																//发送数据
		u8_send_count++;																																			//
		if (u8_send_count>=SEND_LENGTH_OF_ARRAY)																							//发送完成一帧数据，计数器复位
		{
			u8_send_count = 0;																																	//复位发送计数器
			u8_frame_send_stop_count = UART_FRAME_SEND_TIME;																		//帧与帧之间间隔时间，最小60毫秒
			u8_send_state = 0x00;																																//发送完成
		}
	}	
	else																																										//发送间隔期计数
	{
		u8_frame_send_stop_count--;
	}
 }

/**************************************************************************
 * 函数名		：UartReceiveDataBlockCheck()
 * 输入参数 ：无
 * 输出参数 ：无
 * 返回值  	：无
 * 修改时间 ：2019-012-14
 *						修改将原理的值全部异或得0，改成和接收到的异或字做相等比较，原因是发现有时
 *						接收错位但异或结果是0.
 * 函数描述 ：将接收到的值做数据校验后如果数据正确就将完整的数据存放到接收寄存器数组中
 *						
 *************************************************************************/
	void UartReceiveDataBlockCheck(void)
	{
		unsigned char						u8_xor_count = 0,																							//异或校验字节数计数
														u8_xor_temp = 0;																							//异或临时寄存器
														
		if (UartReceivedFlag)
		{
			for (u8_xor_count=0;u8_xor_count<(RECEIVE_LENGTH_OF_ARRAY-1);u8_xor_count++)				//将所有字节中的值做异或
			{
				u8_xor_temp ^= U8_UartReceiveDataBuffer[u8_xor_count];
			}
			
			if (u8_xor_temp==U8_UartReceiveDataBuffer[RECEIVE_LENGTH_OF_ARRAY-1])								//如果数据正确最终的异或值将是等于接收到的校验字
			{			
				for (u8_xor_count=0;u8_xor_count<RECEIVE_LENGTH_OF_ARRAY;u8_xor_count++)					//将缓存的数据保存到接收寄存器中
				{
					U8_UartReceiveData[u8_xor_count] = U8_UartReceiveDataBuffer[u8_xor_count];
				}	
				ControllerConnectFailFlag = FALSE;																								//接收到正确的数据就将通讯故障标志清零，说明通讯接收正常
				
				FirstControllerStateByte = U8_UartReceiveData[REC_STATE_ONE_BYTE_INDEX];					//控制器状态1
				SecondControllerStateByte = U8_UartReceiveData[REC_STATE_TWO_BYTE_INDEX];					//控制器状态2
			}
			
			UartReceivedFlag = FALSE;			
			U8_UartReceiveCount = 0;	
			ENABLE_RECEIVE();
		}
	}
 
/*****************************************************************************************
 * 函数名		：SpeedPerHourCalculate()
 * 输入参数 ：无
 * 输出参数 ：无
 * 返回值  	：无
 * 修改时间 ：2018-09-30
 * 函数描述 ：将接收到的速度反馈数据转换成时速
 *						周长即时速的计算方法：
 *						C= π*D；其中D为轮径，单位为英寸，我们需要将其转换为公制单位KM，因此有：
 *						C= 3.14*D*2.54=D*7.9756CM=(D*7.9756/100000)KM;(1KM=100000CM)；
 *						由于控制器发送给仪表的速度反馈单位为转/毫秒，所以需要将其转化为为转/小时，
 *						T= t/1000(秒)=t/(1000*3600)(小时)；
 *						将上面的值带入速度公式V=C/T；
 *																	V = (D*7.9756/100000)/(t/(1000*3600))= 287*D/t(KM/H)
 *						其中V为时速，单位KM/H；D为轮径，单位英寸；t为时间，控制器发送的数据，单位毫秒
 *
 *						里程数的计算方法：
 *						从上面的计算可以得到时速，那么就有(m/t)=(mi/t1);其中m/t为千米/时，m1/t1为
 *						米/秒，那么t1=m1t/m; 因为计算的是移动100米的时间，所有m1=100，
 *						t1 = 100*3600/m*1000 =360/m,此时t1单位为秒，m为时速值，
 *						举例：时速为10KM/H，则有t1 = 360/10=36秒，即每36秒移动距离为100米
 *****************************************************************************************/
void SpeedPerHourCalculate(unsigned int u16_wheel_distance,   unsigned char 	*p_value) 
{
	unsigned int										u16_cuircumference = 0,																	//周长
																	u16_time_value = 0;																			//时间	
	unsigned int										u16_hundred_meter_time = 0;
	
	static unsigned char						u8_display_jitter = 0;
	static unsigned int							u16_hundred_meter_time_count = 0;

	if ((++u8_display_jitter)>4)																														//500mS做一次显示转换防止显示抖动,这个值变动要修改u16_hundred_meter_time相应值
	{
		u8_display_jitter = 0;
		u16_time_value = (*(p_value+8)<<8)+(*(p_value+9));																		//得到时间
		u16_cuircumference = (u16_wheel_distance*287)/10;																			//将轮径转换为周长，单位KM,除10是因为轮径值扩大了1倍，因此要在此去掉
		if (u16_time_value>0)																																	//除数不能为零，
		{
			U8_SpeedDisplay = (unsigned char)(u16_cuircumference/u16_time_value);								//转换成速度

//----------------------------------------------------------------------------------------//
//速度转换成里程	
			u16_hundred_meter_time = 360/U8_SpeedDisplay;																				//得到移动100米的时间
			u16_hundred_meter_time <<= 1;																												//本函数是在100毫秒时基中调用,显示防抖每500mS执行一次,所以每次调用时间为100*5=500ms,转换成秒就要再乘2
			if ((++u16_hundred_meter_time_count)>u16_hundred_meter_time)												//移动了100米
			{
				u16_hundred_meter_time_count = 0;
				U16_DistanceNumber++;																															//单次里程数加100米，即显示值加0.1
				if ((U16_DistanceNumber%10)==0)																										//每1公里总里程加1
				{
					U16_OdographNumber++;																														//
					OdographNumberWrite(ADDR_EXCURSION_ODO);																				//保存里程数
				}
			}
//----------------------------------------------------------------------------------------//			
		}
		else
		{
			U8_SpeedDisplay = 0;
		}

		//U16_OdographNumber = u16_hundred_meter_time;//for debug
	}
}
 
/**********************SINOWEALTH_SH79F083A**********END OF FILE*************************/
